[C#] Asp.net Mvc 使用 AntiForgery


Posted by mike-hsieh on 2023-12-14

在.net framework mvc 中,時常處理到 XSRF/CSRF 的資安問題,這邊記錄一下使用 axios + filter 的作法。

Step1: 新增一個Filter

public class GlobalAntiForgeryTokenFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        try
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("fail");
            }

            //  如果有AllowAnonymous要忽略驗證,就使用這一段
            object[] controllerAttributes = filterContext.Controller.GetType().GetCustomAttributes(true);
            object[] actionAttributes = filterContext.ActionDescriptor.GetCustomAttributes(true);
            if (controllerAttributes.Any(p => p.ToString().Contains("AllowAnonymousAttribute")) ||
                actionAttributes.Any(p => p.ToString().Contains("AllowAnonymousAttribute")))
            {
                return;
            }

            //  驗證AntiForgeryToken
            var httpMethod = filterContext.HttpContext.Request.HttpMethod.ToUpper();
            if (httpMethod == "POST" && 
                filterContext.HttpContext.Request.IsAjaxRequest() == true)
            {
                var httpContext = filterContext.HttpContext;
                var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName];
                AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]);
            }

            //base.OnActionExecuting(filterContext);
        }
        catch (Exception)
        {
            filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { action = "Logout", controller = "Account" }));

            return;
        }

        base.OnActionExecuting(filterContext);
    }
}

Step2: 在FilterConfig中,註冊該Filter

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            //  這邊加入自訂的驗證過濾器
            filters.Add(new GlobalAntiForgeryTokenFilter);
        }
    }

Step3: 在前端使用Antiforgery,並使用 axios 的 Post 方法

<body>

    <!-- 這邊加入 AntiForgeryToken -->
    @Html.AntiForgeryToken()

    <div>TODO...<div>

    <!-- 這邊加入 cdn axios -->
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

    <script>
        //  取得AntiForgeryToken方法
        function getAntiForgeryToken() {
            var token = document.querySelector('input[name="__RequestVerificationToken"]').value;
            return token;
        }

        //  以下為Post
        axios.post(
            url,            //  'Home/GetData'
            data,           //  { id: 1 }
            {
                'withCredentials': true,
                'headers': {
                    'Content-Type': 'application/json;charset=UTF-8',
                    'X-Requested-With': 'XMLHttpRequest',   // For IsAjaxRequest()
                    __RequestVerificationToken: getAntiForgeryToken(),      //  這邊加入 AntiForgeryToken
                },
            },
        ).then(resp => {
            //  TODO...
        }).catch(err => {
            //  TODO...
        })
    </script>

</body>

#XSRF #csrf #AntiForgery #ASP.NET MVC #Axios #filter







Related Posts

HTML 標籤元素與屬性介紹

HTML 標籤元素與屬性介紹

create react app 專案 git push 推不上 remote repo

create react app 專案 git push 推不上 remote repo

氣泡排序(Bubble Sort)、插入排序(Insertion Sort)、選擇排序(Selection Sort)

氣泡排序(Bubble Sort)、插入排序(Insertion Sort)、選擇排序(Selection Sort)


Comments